/*
 * @Author: xujiawei 
 * @Date: 2021-07-21 15:12:33 
 * @Last Modified by: xujiawei
 * @Last Modified time: 2021-08-03 11:00:25
 * 可拖拽物品
 */

import { IDragContainer } from "./DragContainer";

const { ccclass, property } = cc._decorator;
@ccclass
export class DragItem extends cc.Component {
    itemID: number = -1; // item id, 一个容器可以选择接收多种不同类型的item
    touchEnable: boolean = true;
    protected options: IDragContainer[] = []; // 一个item也可能可以拖往多个container里
    protected originPos: cc.Vec2 = null;
    protected rollbackSpeed: number = 200;
    protected onDragStartCb: Function = null;
    protected onDragEnd: Function = null;
    private _draged: boolean = false; // 是否拖动了
    private _oriZindex: number = 0;

    init(option: IDragContainer[]) {
        this.options = option;
    }
    
    onEnable() {
        this._registerEvent();
    }

    onDisable() {
        this._unregisterEvent();
    }

    setOnDragStartCb(cb: Function) {
        this.onDragStartCb = cb;
    }

    setOnDragEndCb(cb: Function) {
        this.onDragEnd = cb;
    }

    private _registerEvent() {
        this.node.on(cc.Node.EventType.TOUCH_START, this._touchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this._touchEnd, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._touchCancle, this);
    }

    private _unregisterEvent() {
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this._touchStart, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this._touchEnd, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._touchCancle, this);
    }

    private _touchStart(event: cc.Event.EventTouch) {
        if (!this.originPos) {
            this.originPos = this.node.getPosition();
            this._oriZindex = this.node.zIndex;
        }
        this.node.zIndex = cc.macro.MAX_ZINDEX - 1;
    }

    private _touchMove(event: cc.Event.EventTouch) {
        if (!this.touchEnable) return;
        if (!this._draged) {
            this._draged = true;
            this.onDragStart();
        }

        let delta = event.getDelta();
        this.node.x += delta.x;
        this.node.y += delta.y;
        for (let option of this.options) {
            option && option.onItemMove && option.onItemMove(this.node, this.itemID);
        }
    }

    private _touchEnd(event: cc.Event.EventTouch) {
        if (!this.touchEnable) return;
        this._checkIn();
    }

    private _touchCancle(event: cc.Event.EventTouch) {
        if (!this.touchEnable) return;
        this._checkIn();
    }

    // 拖入容器是否成功
    private _checkIn() {
        this._draged = false;
        this.touchEnable = false;

        for (let option of this.options) {
            if (option && option.checkInContainer(this.node, this.itemID)) {
                this.node.zIndex = this._oriZindex;
                this.onDragSuc();
                return;
            } 
        }

        const distance: number = cc.Vec2.distance(this.originPos, this.node.getPosition());
        const t = distance / this.rollbackSpeed / 10;
        cc.Tween.stopAllByTarget(this.node);
        cc.tween(this.node).to(t, {position: cc.v3(this.originPos)}, { easing: 'sineOut'}).call(()=>{
            this.node.zIndex = this._oriZindex;
            this.onDragFail();
            this.touchEnable = true;
        }).start();
    }

    protected onDragStart() {
        this.onDragStartCb && this.onDragStartCb();
    }
    
    protected onDragSuc() {
        this.onDragEnd && this.onDragEnd(true);
    }

    protected onDragFail() {
        this.onDragEnd && this.onDragEnd(false);
    }
}